# 2021-8-26 新增按月份分析功能 by grx
import math
import datetime

from rest_framework.decorators import api_view
from questionnaire.models import *
from rest_framework.response import Response
from rest_framework import status


@api_view(['POST', ])
def getQuestionInfo(request):
    # 获取问卷id
    wid = request.data.get('qid')
    # [{ value: '问题id', label: '问题名' }, { value: '问题id', label: '问题名'  }, {value: '问题id', label: '问题名'  }, { value: '问题id', label: '问题名' }, { value: '问题id', label: '问题名' }]
    if wid:
        # 找出问卷所包含的所有选择题和评分题
        questions = Question.objects.filter(wjId=wid).filter(type__in=['single', 'multi', 'grade'])
        # 初始化需要返回的列表
        question_info = []
        for q in questions:
            question_info.append({'value': q.id, 'label': q.title})
        response = {
            'code': 0,
            'msg': 'success',
            'question_info': question_info
        }
    else:
        response = {
            'code': 1,
            'msg': '获取问卷id失败'
        }
    return Response(response, status=status.HTTP_200_OK)


@api_view(['POST', ])
def crossStatistics(request):
    # 获取所需要做的交叉分析的种类
    statistic_type = request.data.get('type')
    # 1-1
    if statistic_type == '1q_1q':
        xid = request.data.get('xid')
        yid = request.data.get('yid')
        # 判断数据是否有效
        if xid and yid:
            # 对每一个有效提交，找到其对应x和y的回答
            # 应该生成{x-option1:{y-option1:num, y-option2:num, ...}, x-option2:{...}, ...}
            # 获取xid&yid对应的type, 并根据此 找到x,y对应的选项列表
            q_x = Question.objects.filter(id=xid).first()
            q_y = Question.objects.filter(id=yid).first()

            if q_x.type in ['single', 'multi']:
                o_x = Options.objects.filter(questionId=xid)
            elif q_x.type == 'grade':
                o_x = GradeQuestionAttribute.objects.filter(questionId=xid).first()
            else:
                o_x = None

            if q_y.type in ['single', 'multi']:
                o_y = Options.objects.filter(questionId=yid)
            elif q_y.type == 'grade':
                o_y = GradeQuestionAttribute.objects.filter(questionId=yid).first()
            else:
                o_y = None
            # 判断查找是否成功
            if o_x and o_y:
                # 返回统计结果的字典
                statistic_d = {}
                # 找到所有有效回答的submit列表
                wid = Question.objects.filter(id=xid).first().wjId
                submitted_ls = Submit.objects.filter(wjId=wid).filter(is_submitted=True)
                x_data = []
                series = []
                # 分别计算q_x题选择x选项的人中，q_y题各选项的分布
                if q_x.type in ['single', 'multi']:
                    # x_data
                    x_data = list(o_x.values_list('title', flat=True).distinct())
                    for x in o_x:
                        # 初始化子字典，形成如{x-option1:{}, x-option2:{}, ...}的结构
                        statistic_d[x.title] = {}
                        # 初始化子字典，形成如{x-option1:{y-option1:0, y-option2:0, ...}, x-option2:{...}, ...}的结构
                        if q_y.type in ['single', 'multi']:
                            for y in o_y:
                                statistic_d[x.title][y.title] = 0
                                # series.append({'name': y.title, 'data': [0] * len(o_x)})
                        else:
                            for i in range(o_y.start, o_y.start + o_y.range):
                                statistic_d[x.title][i] = 0
                                # series.append({'name': i, 'data': [0] * len(o_x)})
                        # 找到所有有效的q_x题选择x的answer对应的submitId列表
                        sub_x = list(Answer.objects.filter(questionId=xid).filter(answer=x.id).filter(submitId__in=submitted_ls).values_list('submitId', flat=True).distinct())
                        # 找到所有有效的y_x题的answer, 且该回答对应的submitId也在q_x中选择了x
                        ans_y = Answer.objects.filter(questionId=yid).filter(submitId__in=sub_x)
                        for a in ans_y:
                            # 获取a.answer对应的选项标题
                            if q_y.type in ['single', 'multi']:
                                title = Options.objects.filter(id=a.answer).first().title
                                # 判断title是否正确
                                if title in list(o_y.values_list('title', flat=True).distinct()):
                                    statistic_d[x.title][title] += 1
                            else:
                                title = a.answer
                                # 判断title是否正确
                                if title - o_y.start < o_y.range:
                                    statistic_d[x.title][title] += 1
                else:
                    for i_x in range(o_x.start, o_x.start + o_x.range):
                        # 初始化子字典，形成如{x-option1:{}, x-option2:{}, ...}的结构
                        statistic_d[i_x] = {}
                        # x_data
                        x_data.append(i_x)
                        # 初始化子字典，形成如{x-option1:{y-option1:0, y-option2:0, ...}, x-option2:{...}, ...}的结构
                        if q_y.type in ['single', 'multi']:
                            for y in o_y:
                                statistic_d[i_x][y.title] = 0
                                # series.append({'name': y.title, 'data': [0] * o_x.range})
                        else:
                            for i in range(o_y.start, o_y.start + o_y.range):
                                statistic_d[i_x][i] = 0
                                # series.append({'name': i, 'data': [0] * o_x.range})
                        # 找到所有有效的q_x题选择x的answer对应的submitId列表
                        sub_x = list(Answer.objects.filter(questionId=xid).filter(answer=i_x).filter(submitId__in=submitted_ls).values_list('submitId', flat=True).distinct())
                        # 找到所有有效的y_x题的answer, 且该回答对应的submitId也在q_x中选择了x
                        ans_y = Answer.objects.filter(questionId=yid).filter(submitId__in=sub_x)
                        for a in ans_y:
                            # 获取a.answer对应的选项标题
                            if q_y.type in ['single', 'multi']:
                                title = Options.objects.filter(id=a.answer).first().title
                                # 判断title是否正确
                                if title in list(o_y.values_list('title', flat=True).distinct()):
                                    statistic_d[i_x][title] += 1
                            else:
                                title = a.answer
                                # 判断title是否正确
                                if title - o_y.start < o_y.range:
                                    statistic_d[i_x][title] += 1

                # 生成series
                y_data = []
                if q_y.type in ['single', 'multi']:
                    for y in o_y:
                        y_data.append(y.title)
                        if q_x.type in ['single', 'multi']:
                            series.append({'name': y.title, 'data': [0] * len(x_data)})
                        else:
                            series.append({'name': y.title, 'data': [0] * o_x.range})
                else:
                    for i in range(o_y.start, o_y.start + o_y.range):
                        y_data.append(i)
                        if q_x.type in ['single', 'multi']:
                            series.append({'name': i, 'data': [0] * len(x_data)})
                        else:
                            series.append({'name': i, 'data': [0] * o_x.range})
                print(statistic_d)
                print(x_data)
                print(y_data)
                print(series)
                # 向series中填入数据
                for j in range(len(series)):
                    for k in range(len(series[j]['data'])):
                        print('j, k = ' + str(j) + ', ' + str(k))
                        series[j]['data'][k] = statistic_d[x_data[k]][y_data[j]]
                response = {
                    'code': 0,
                    'msg': 'success',
                    'x_data': x_data,
                    'series': series,
                    'cross_statistic': statistic_d
                }
            else:
                response = {
                    'code': 3,
                    'msg': 'o_x 或 o_y 查找失败：传入的xid及yid并非选项题id或对应问卷不存在选项或id无效'
                }
        else:
            response = {
                'code': 2,
                'msg': 'xid 或 yid 为空'
            }
    # t-1
    elif statistic_type == 't_1q':
        time_type = request.data.get('time_type')
        qid = request.data.get('qid')
        # 判断数据是否有效
        if time_type and qid:
            question = Question.objects.filter(id=qid).first()
            if question and question.type in ['single', 'multi', 'grade']:
                if time_type == 'year':
                    source = []
                    # 生成product列
                    # 此处可扩展功能：由用户选择展示多少年
                    product = ['product']
                    this_year = int(datetime.date.today().year)
                    div = 6
                    for i in range(1, div + 1):
                        product.append(str(this_year - div + i))
                    source.append(product)
                    # 循环生成数据列
                    # 找到所有有效回答的submit列表
                    wid = Question.objects.filter(id=qid).first().wjId
                    submitted_ls = Submit.objects.filter(wjId=wid).filter(is_submitted=True)
                    # 获取所有选项：分类讨论
                    if question.type in ['single', 'multi']:
                        options = Options.objects.filter(questionId=qid)
                        titles = list(options.values_list('title', flat=True).distinct())
                        # 初始化列表[...,[title, 0, 0, 0, ...], ...]
                        for t in titles:
                            source.append([t, 0])
                            source[-1].extend([0] * (len(source[0]) - 2))
                        # 计算填充数据
                        ans = Answer.objects.filter(questionId=qid).filter(submitId__in=submitted_ls)
                        for a in ans:
                            # 获取填写时间
                            sub_time = str(Submit.objects.filter(id=a.submitId).first().submitTime.year)
                            ans_title = Options.objects.filter(id=a.answer).first().title
                            if sub_time in source[0] and ans_title in titles:
                                j = source[0].index(sub_time)
                                i = titles.index(ans_title) + 1
                                source[i][j] += 1
                    else:
                        options = GradeQuestionAttribute.objects.filter(questionId=qid).first()
                        titles = [i + options.start for i in range(0, options.range)]
                        # 初始化列表[...,[title, 0, 0, 0, ...], ...]
                        for t in titles:
                            source.append([t, 0])
                            source[-1].extend([0] * (len(source[0]) - 2))
                        # 计算填充数据
                        ans = Answer.objects.filter(questionId=qid).filter(submitId__in=submitted_ls)
                        for a in ans:
                            # 获取填写时间
                            sub_time = str(Submit.objects.filter(id=a.submitId).first().submitTime.year)
                            ans_title = a.answer
                            if sub_time in source[0] and ans_title in titles:
                                j = source[0].index(sub_time)
                                i = titles.index(ans_title) + 1
                                source[i][j] += 1

                    response = {
                        'code': 0,
                        'msg': 'success',
                        'source': source
                    }
                elif time_type == 'month':
                    source = []
                    # 生成product列
                    # 此处可扩展功能：由用户选择展示多少年
                    product = ['product']
                    this_year = str(datetime.date.today().year)
                    last_year = str(int(this_year) - 1)
                    this_month = datetime.date.today().month
                    div = 6
                    for i in range(1, div + 1):
                        if this_month - div + i >= 1:
                            product.append(str(this_month - div + i))
                        else:
                            product.append(str(this_month - div + i + 12))
                    source.append(product)
                    # 循环生成数据列
                    # 找到所有有效回答的submit列表
                    wid = Question.objects.filter(id=qid).first().wjId
                    submitted_ls = Submit.objects.filter(wjId=wid).filter(is_submitted=True)
                    print('submit_ls = ', submitted_ls)
                    # 获取所有选项：分类讨论
                    if question.type in ['single', 'multi']:
                        options = Options.objects.filter(questionId=qid)
                        titles = list(options.values_list('title', flat=True).distinct())
                        # 初始化列表[...,[title, 0, 0, 0, ...], ...]
                        for t in titles:
                            source.append([t, 0])
                            source[-1].extend([0] * (len(source[0]) - 2))
                        # 计算填充数据
                        ans = Answer.objects.filter(questionId=qid).filter(submitId__in=submitted_ls)
                        for a in ans:
                            # 获取填写时间
                            sub_year = str(Submit.objects.filter(id=a.submitId).first().submitTime.year)
                            sub_month = str(Submit.objects.filter(id=a.submitId).first().submitTime.month)
                            ans_title = Options.objects.filter(id=a.answer).first().title
                            if (sub_year in [last_year, this_year]) and (sub_month in source[0]) and (ans_title in titles):
                                j = source[0].index(sub_month)
                                i = titles.index(ans_title) + 1
                                source[i][j] += 1
                    else:
                        options = GradeQuestionAttribute.objects.filter(questionId=qid).first()
                        titles = [i + options.start for i in range(0, options.range)]
                        # 初始化列表[...,[title, 0, 0, 0, ...], ...]
                        for t in titles:
                            source.append([t, 0])
                            source[-1].extend([0] * (len(source[0]) - 2))
                        # 计算填充数据
                        ans = Answer.objects.filter(questionId=qid).filter(submitId__in=submitted_ls)
                        for a in ans:
                            # 获取填写时间
                            sub_year = str(Submit.objects.filter(id=a.submitId).first().submitTime.year)
                            sub_month = str(Submit.objects.filter(id=a.submitId).first().submitTime.month)
                            ans_title = a.answer
                            if (sub_year in [last_year, this_year]) and (sub_month in source[0]) and (ans_title in titles):
                                j = source[0].index(sub_month)
                                i = titles.index(ans_title) + 1
                                source[i][j] += 1

                    response = {
                        'code': 0,
                        'msg': 'success',
                        'source': source
                    }
                elif time_type == 'day':
                    source = []
                    # 生成product列
                    # 此处可扩展功能：由用户选择展示多少年
                    product = ['product']
                    today = datetime.date.today()
                    this_year = today.year
                    last_year = this_year - 1
                    this_month = today.month
                    last_month = this_month - 1 if this_month - 1 > 0 else this_month + 11
                    this_day = today.day
                    div = 6
                    for i in range(1, div + 1):
                        if this_day - div + i >= 1:
                            product.append(str(this_month) + '.' + str(this_day - div + i))     # month.day
                        else:
                            # 上个月有31天的
                            if last_month in [1, 3, 5, 7, 8, 10, 12]:
                                product.append(str(last_month) + '.' + str(this_day - div + i + 31))
                            # 30
                            elif last_month in [4, 6, 9, 11]:
                                product.append(str(last_month) + '.' + str(this_day - div + i + 30))
                            else:
                                if this_year % 4 != 0 or (this_year % 100 == 0 and this_year % 400 != 0):
                                    product.append(str(last_month) + '.' + str(this_day - div + i + 28))
                                else:
                                    product.append(str(last_month) + '.' + str(this_day - div + i + 29))

                    source.append(product)
                    # 循环生成数据列
                    # 找到所有有效回答的submit列表
                    wid = Question.objects.filter(id=qid).first().wjId
                    submitted_ls = Submit.objects.filter(wjId=wid).filter(is_submitted=True)
                    # 获取所有选项：分类讨论
                    if question.type in ['single', 'multi']:
                        options = Options.objects.filter(questionId=qid)
                        titles = list(options.values_list('title', flat=True).distinct())
                        # 初始化列表[...,[title, 0, 0, 0, ...], ...]
                        for t in titles:
                            source.append([t, 0])
                            source[-1].extend([0] * (len(source[0]) - 2))
                        # 计算填充数据
                        ans = Answer.objects.filter(questionId=qid).filter(submitId__in=submitted_ls)
                        for a in ans:
                            # 获取填写时间
                            sub_year = Submit.objects.filter(id=a.submitId).first().submitTime.year
                            sub_month = str(Submit.objects.filter(id=a.submitId).first().submitTime.month)
                            sub_day = str(Submit.objects.filter(id=a.submitId).first().submitTime.day)
                            ans_title = Options.objects.filter(id=a.answer).first().title
                            if (sub_year in [last_year, this_year]) and (sub_month + '.' + sub_day in source[0]) and (ans_title in titles):
                                j = source[0].index(sub_month + '.' + sub_day)
                                i = titles.index(ans_title) + 1
                                source[i][j] += 1
                    else:
                        options = GradeQuestionAttribute.objects.filter(questionId=qid).first()
                        titles = [i + options.start for i in range(0, options.range)]
                        # 初始化列表[...,[title, 0, 0, 0, ...], ...]
                        for t in titles:
                            source.append([t, 0])
                            source[-1].extend([0] * (len(source[0]) - 2))
                        # 计算填充数据
                        ans = Answer.objects.filter(questionId=qid).filter(submitId__in=submitted_ls)
                        for a in ans:
                            # 获取填写时间
                            sub_year = Submit.objects.filter(id=a.submitId).first().submitTime.year
                            sub_month = str(Submit.objects.filter(id=a.submitId).first().submitTime.month)
                            sub_day = str(Submit.objects.filter(id=a.submitId).first().submitTime.day)
                            ans_title = a.answer
                            if (sub_year in [last_year, this_year]) and (sub_month + '.' + sub_day in source[0]) and (ans_title in titles):
                                j = source[0].index(sub_month + '.' + sub_day)
                                i = titles.index(ans_title) + 1
                                source[i][j] += 1

                    response = {
                        'code': 0,
                        'msg': 'success',
                        'source': source
                    }
                else:
                    response = {
                        'code': 4,
                        'msg': 'time_type为无效的种类'
                    }
            else:
                response = {
                    'code': 3,
                    'msg': '未在数据库中查询到对应问题，或问题类型错误'
                }
        else:
            response = {
                'code': 2,
                'msg': 'qid 或 time_type 为空'
            }
    else:
        response = {
            'code': 1,
            'msg': 'statistic_type 为不存在的类型'
        }
    return Response(response, status=status.HTTP_200_OK)
